home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / rpc3.9 / part12 < prev    next >
Encoding:
Internet Message Format  |  1988-02-27  |  60.7 KB

  1. Subject:  v13i089:  Sun RPC, release 3.9, Part12/15
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Stephen X. Nahm <sxn@Sun.COM>
  7. Posting-number: Volume 13, Issue 89
  8. Archive-name: rpc3.9/part12
  9.  
  10. #! /bin/sh
  11. # This is a shell archive. To extract, remove the header and type "sh filename"
  12. #
  13. cd doc
  14. echo x - rpc.rfc.ms
  15. sed -e 's/^X//' > rpc.rfc.ms <<'Funky_Stuff'
  16. X.\" @(#)rpc.rfc.ms    1.2 87/11/09 3.9 RPCSRC
  17. X.de BT
  18. X.if \\n%=1 .tl ''- % -''
  19. X..
  20. X.ND
  21. X.\" prevent excess underlining in nroff
  22. X.if n .fp 2 R
  23. X.OH 'Remote Procedure Calls: Protocol Specification''Page %'
  24. X.EH 'Page %''Remote Procedure Calls: Protocol Specification'
  25. X.if \\n%=1 .bp
  26. X.SH
  27. \&Remote Procedure Calls: Protocol Specification
  28. X.LP
  29. X.NH 0
  30. \&Status of this Memo
  31. X.LP
  32. Note: This chapter specifies a protocol that Sun Microsystems, Inc.,
  33. and others are using.  It has been submitted to the ARPA-Internet
  34. for consideration as an RFC.  \fBCertain details may change as a result
  35. of comments made during the review of this draft standard.\fP  
  36. X.LP
  37. X.NH 1
  38. \&Introduction
  39. X.LP
  40. This chapter specifies  a  message protocol  used in implementing
  41. Sun's Remote Procedure Call (RPC) package.  (The message protocol is
  42. specified with the eXternal Data Representation (XDR) language.
  43. See the
  44. \fIeXternal Data Representation Standard\fP
  45. for the details.  Here, we assume that  the  reader is familiar  
  46. with XDR and do not attempt to justify RPC or  its uses).  The paper
  47. by Birrell and Nelson [1]  is recommended as an  excellent background
  48. to  and justification of RPC.
  49. X.NH 2
  50. \&Terminology
  51. X.LP
  52. This chapter discusses servers, services, programs, procedures,
  53. clients, and versions.  A server is a piece of software where network
  54. services are implemented.  A network service is a collection of one
  55. or more remote programs.  A remote program implements one or more
  56. remote procedures; the procedures, their parameters, and results are
  57. documented in the specific program's protocol specification (see the
  58. \fIPort Mapper Program Protocol\fP\, below, for an example).  Network
  59. clients are pieces of software that initiate remote procedure calls
  60. to services.  A server may support more than one version of a remote
  61. program in order to be forward compatible with changing protocols.
  62. X.LP
  63. For example, a network file service may be composed of two programs.
  64. One program may deal with high-level applications such as file system
  65. access control and locking.  The other may deal with low-level file
  66. IO and have procedures like "read" and "write".  A client machine of
  67. the network file service would call the procedures associated with
  68. the two programs of the service on behalf of some user on the client
  69. machine.
  70. X.NH 2
  71. \&The RPC Model
  72. X.LP
  73. The remote procedure call model is similar to the local procedure
  74. call model.  In the local case, the caller places arguments to a
  75. procedure in some well-specified location (such as a result
  76. register).  It then transfers control to the procedure, and
  77. eventually gains back control.  At that point, the results of the
  78. procedure are extracted from the well-specified location, and the
  79. caller continues execution.
  80. X.LP
  81. The remote procedure call is similar, in that one thread of control
  82. logically winds through two processes\(emone is the caller's process,
  83. the other is a server's process.  That is, the caller process sends a
  84. call message to the server process and waits (blocks) for a reply
  85. message.  The call message contains the procedure's parameters, among
  86. other things.  The reply message contains the procedure's results,
  87. among other things.  Once the reply message is received, the results
  88. of the procedure are extracted, and caller's execution is resumed.
  89. X.LP
  90. On the server side, a process is dormant awaiting the arrival of a
  91. call message.  When one arrives, the server process extracts the
  92. procedure's parameters, computes the results, sends a reply message,
  93. and then awaits the next call message.
  94. X.LP
  95. Note that in this model, only one of the two processes is active at
  96. any given time.  However, this model is only given as an example.
  97. The RPC protocol makes no restrictions on the concurrency model
  98. implemented, and others are possible.  For example, an implementation
  99. may choose to have RPC calls be asynchronous, so that the client may
  100. do useful work while waiting for the reply from the server.  Another
  101. possibility is to have the server create a task to process an
  102. incoming request, so that the server can be free to receive other
  103. requests.
  104. X.NH 2
  105. \&Transports and Semantics
  106. X.LP
  107. The RPC protocol is independent of transport protocols.  That is, RPC
  108. does not care how a message is passed from one process to another.
  109. The protocol deals only with specification and interpretation of
  110. messages.
  111. X.LP
  112. It is important to point out that RPC does not try to implement any
  113. kind of reliability and that the application must be aware of the
  114. type of transport protocol underneath RPC.  If it knows it is running
  115. on top of a reliable transport such as TCP/IP[6], then most of the
  116. work is already done for it.  On the other hand, if it is running on
  117. top of an unreliable transport such as UDP/IP[7], it must implement
  118. is own retransmission and time-out policy as the RPC layer does not
  119. provide this service.
  120. X.LP
  121. Because of transport independence, the RPC protocol does not attach
  122. specific semantics to the remote procedures or their execution.
  123. Semantics can be inferred from (but should be explicitly specified
  124. by) the underlying transport protocol.  For example, consider RPC
  125. running on top of an unreliable transport such as UDP/IP.  If an
  126. application retransmits RPC messages after short time-outs, the only
  127. thing it can infer if it receives no reply is that the procedure was
  128. executed zero or more times.  If it does receive a reply, then it can
  129. infer that the procedure was executed at least once.
  130. X.LP
  131. A server may wish to remember previously granted requests from a
  132. client and not regrant them in order to insure some degree of
  133. execute-at-most-once semantics.  A server can do this by taking
  134. advantage of the transaction ID that is packaged with every RPC
  135. request.  The main use of this transaction is by the client RPC layer
  136. in matching replies to requests.  However, a client application may
  137. choose to reuse its previous transaction ID when retransmitting a
  138. request.  The server application, knowing this fact, may choose to
  139. remember this ID after granting a request and not regrant requests
  140. with the same ID in order to achieve some degree of
  141. execute-at-most-once semantics.  The server is not allowed to examine
  142. this ID in any other way except as a test for equality.
  143. X.LP
  144. On the other hand, if using a reliable transport such as TCP/IP, the
  145. application can infer from a reply message that the procedure was
  146. executed exactly once, but if it receives no reply message, it cannot
  147. assume the remote procedure was not executed.  Note that even if a
  148. connection-oriented protocol like TCP is used, an application still
  149. needs time-outs and reconnection to handle server crashes.
  150. X.LP
  151. There are other possibilities for transports besides datagram- or
  152. connection-oriented protocols.  For example, a request-reply protocol
  153. such as VMTP[2] is perhaps the most natural transport for RPC.
  154. X.SH
  155. X.I
  156. NOTE:  At Sun, RPC is currently implemented on top of both TCP/IP
  157. and UDP/IP transports.
  158. X.LP
  159. X.NH 2
  160. \&Binding and Rendezvous Independence
  161. X.LP
  162. The act of binding a client to a service is NOT part of the remote
  163. procedure call specification.  This important and necessary function
  164. is left up to some higher-level software.  (The software may use RPC
  165. itself\(emsee the \fIPort Mapper Program Protocol\fP\, below).
  166. X.LP
  167. Implementors should think of the RPC protocol as the jump-subroutine
  168. instruction ("JSR") of a network; the loader (binder) makes JSR
  169. useful, and the loader itself uses JSR to accomplish its task.
  170. Likewise, the network makes RPC useful, using RPC to accomplish this
  171. task.
  172. X.NH 2
  173. \&Authentication
  174. X.LP
  175. The RPC protocol provides the fields necessary for a client to
  176. identify itself to a service and vice-versa.  Security and access
  177. control mechanisms can be built on top of the message authentication.
  178. Several different authentication protocols can be supported.  A field
  179. in the RPC header indicates which protocol is being used.  More
  180. information on specific authentication protocols can be found in the
  181. \fIAuthentication Protocols\fP\,
  182. below.
  183. X.KS
  184. X.NH 1
  185. \&RPC Protocol Requirements
  186. X.LP
  187. The RPC protocol must provide for the following:
  188. X.IP  1.
  189. Unique specification of a procedure to be called.
  190. X.IP  2.
  191. Provisions for matching response messages to request messages.
  192. X.KE
  193. X.IP  3.
  194. Provisions for authenticating the caller to service and vice-versa.
  195. X.LP
  196. Besides these requirements, features that detect the following are
  197. worth supporting because of protocol roll-over errors, implementation
  198. bugs, user error, and network administration:
  199. X.IP  1.
  200. RPC protocol mismatches.
  201. X.IP  2.
  202. Remote program protocol version mismatches.
  203. X.IP  3.
  204. Protocol errors (such as misspecification of a procedure's parameters).
  205. X.IP  4.
  206. Reasons why remote authentication failed.
  207. X.IP  5.
  208. Any other reasons why the desired procedure was not called.
  209. X.NH 2
  210. \&Programs and Procedures
  211. X.LP
  212. The RPC call message has three unsigned fields:  remote program
  213. number, remote program version number, and remote procedure number.
  214. The three fields uniquely identify the procedure to be called.
  215. Program numbers are administered by some central authority (like
  216. Sun).  Once an implementor has a program number, he can implement his
  217. remote program; the first implementation would most likely have the
  218. version number of 1.  Because most new protocols evolve into better,
  219. stable, and mature protocols, a version field of the call message
  220. identifies which version of the protocol the caller is using.
  221. Version numbers make speaking old and new protocols through the same
  222. server process possible.
  223. X.LP
  224. The procedure number identifies the procedure to be called.  These
  225. numbers are documented in the specific program's protocol
  226. specification.  For example, a file service's protocol specification
  227. may state that its procedure number 5 is "read" and procedure number
  228. 12 is "write".
  229. X.LP
  230. Just as remote program protocols may change over several versions,
  231. the actual RPC message protocol could also change.  Therefore, the
  232. call message also has in it the RPC version number, which is always
  233. equal to two for the version of RPC described here.
  234. X.LP
  235. The reply message to a request  message  has enough  information to
  236. distinguish the following error conditions:
  237. X.IP  1.
  238. The remote implementation of RPC does speak protocol version 2.
  239. The lowest and highest supported RPC version numbers are returned.
  240. X.IP  2.
  241. The remote program is not available on the remote system.
  242. X.IP  3.
  243. The remote program does not support the requested version number.
  244. The lowest and highest supported remote program version numbers are
  245. returned.
  246. X.IP  4.
  247. The requested procedure number does not exist.  (This is usually a
  248. caller side protocol or programming error.)
  249. X.IP  5.
  250. The parameters to the remote procedure appear to be garbage from the
  251. server's point of view.  (Again, this is usually caused by a
  252. disagreement about the protocol between client and service.)
  253. X.NH 2
  254. \&Authentication
  255. X.LP
  256. Provisions for authentication of caller to service and vice-versa are
  257. provided as a part of the RPC protocol.  The call message has two
  258. authentication fields, the credentials and verifier.  The reply
  259. message has one authentication field, the response verifier.  The RPC
  260. protocol specification defines all three fields to be the following
  261. opaque type:
  262. X.DS
  263. X.ft CW
  264. X.vs 11
  265. enum auth_flavor {
  266.     AUTH_NULL        = 0,
  267.     AUTH_UNIX        = 1,
  268.     AUTH_SHORT       = 2,
  269.     /* \fIand more to be defined\fP */
  270. };
  271.  
  272. struct opaque_auth {
  273.     auth_flavor flavor;
  274.     opaque body<400>;
  275. };
  276. X.DE
  277. X.LP
  278. In simple English, any
  279. X.I opaque_auth 
  280. structure is an 
  281. X.I auth_flavor 
  282. enumeration followed by bytes which are  opaque to the RPC protocol
  283. implementation.
  284. X.LP
  285. The interpretation and semantics  of the data contained  within the
  286. authentication   fields  is specified  by  individual,  independent
  287. authentication  protocol specifications.   (See 
  288. \fIAuthentication Protocols\fP\,
  289. below, for definitions of the various authentication protocols.)
  290. X.LP
  291. If authentication parameters were   rejected, the  response message
  292. contains information stating why they were rejected.
  293. X.NH 2
  294. \&Program Number Assignment
  295. X.LP
  296. Program numbers are given out in groups of
  297. X.I 0x20000000 
  298. (decimal 536870912) according to the following chart:
  299. X.TS
  300. box tab (&) ;
  301. lfI lfI
  302. rfL cfI .
  303. Program Numbers&Description
  304. _
  305. X.sp .5
  306. 0 - 1fffffff&Defined by Sun
  307. 20000000 - 3fffffff&Defined by user
  308. 40000000 - 5fffffff&Transient
  309. 60000000 - 7fffffff&Reserved
  310. 80000000 - 9fffffff&Reserved
  311. a0000000 - bfffffff&Reserved
  312. c0000000 - dfffffff&Reserved
  313. e0000000 - ffffffff&Reserved
  314. X.TE
  315. X.LP
  316. The first group is a range of numbers administered by Sun
  317. Microsystems and should be identical for all sites.  The second range
  318. is for applications peculiar to a particular site.  This range is
  319. intended primarily for debugging new programs.  When a site develops
  320. an application that might be of general interest, that application
  321. should be given an assigned number in the first range.  The third
  322. group is for applications that generate program numbers dynamically.
  323. The final groups are reserved for future use, and should not be used.
  324. X.NH 2
  325. \&Other Uses of the RPC Protocol
  326. X.LP
  327. The intended use of this protocol is for calling remote procedures.
  328. That is, each call message is matched with a response message.
  329. However, the protocol itself is a message-passing protocol with which
  330. other (non-RPC) protocols can be implemented.  Sun currently uses, or
  331. perhaps abuses, the RPC message protocol for the following two
  332. (non-RPC) protocols:  batching (or pipelining) and broadcast RPC.
  333. These two protocols are discussed but not defined below.
  334. X.NH 3
  335. \&Batching
  336. X.LP
  337. Batching allows a client to send an arbitrarily large sequence of
  338. call messages to a server; batching typically uses reliable byte
  339. stream protocols (like TCP/IP) for its transport.  In the case of
  340. batching, the client never waits for a reply from the server, and the
  341. server does not send replies to batch requests.  A sequence of batch
  342. calls is usually terminated by a legitimate RPC in order to flush the
  343. pipeline (with positive acknowledgement).
  344. X.NH 3
  345. \&Broadcast RPC
  346. X.LP
  347. In broadcast RPC-based protocols, the client sends a broadcast packet
  348. to the network and waits for numerous replies.  Broadcast RPC uses
  349. unreliable, packet-based protocols (like UDP/IP) as its transports.
  350. Servers that support broadcast protocols only respond when the
  351. request is successfully processed, and are silent in the face of
  352. errors.  Broadcast RPC uses the Port Mapper RPC service to achieve
  353. its semantics.  See the \fIPort Mapper Program Protocol\fP\, below,
  354. for more information.
  355. X.KS
  356. X.NH 1
  357. \&The RPC Message Protocol
  358. X.LP
  359. This section defines the RPC message protocol in the XDR data
  360. description language.  The message is defined in a top-down style.
  361. X.ie t .DS
  362. X.el .DS L
  363. X.ft CW
  364. enum msg_type {
  365.     CALL  = 0,
  366.     REPLY = 1
  367. };
  368.  
  369. X.ft I
  370. /*
  371. * A reply to a call message can take on two forms:
  372. * The message was either accepted or rejected.
  373. */
  374. X.ft CW
  375. enum reply_stat {
  376.     MSG_ACCEPTED = 0,
  377.     MSG_DENIED   = 1
  378. };
  379.  
  380. X.ft I
  381. /*
  382. * Given that a call message was accepted,  the following is the
  383. * status of an attempt to call a remote procedure.
  384. */
  385. X.ft CW
  386. enum accept_stat {
  387.     SUCCESS       = 0, /* \fIRPC executed successfully       \fP*/
  388.     PROG_UNAVAIL  = 1, /* \fIremote hasn't exported program  \fP*/
  389.     PROG_MISMATCH = 2, /* \fIremote can't support version #  \fP*/
  390.     PROC_UNAVAIL  = 3, /* \fIprogram can't support procedure \fP*/
  391.     GARBAGE_ARGS  = 4  /* \fIprocedure can't decode params   \fP*/
  392. };
  393. X.DE
  394. X.ie t .DS
  395. X.el .DS L
  396. X.ft I
  397. /*
  398. * Reasons why a call message was rejected:
  399. */
  400. X.ft CW
  401. enum reject_stat {
  402.     RPC_MISMATCH = 0, /* \fIRPC version number != 2          \fP*/
  403.     AUTH_ERROR = 1    /* \fIremote can't authenticate caller \fP*/
  404. };
  405.  
  406. X.ft I
  407. /*
  408. * Why authentication failed:
  409. */
  410. X.ft CW
  411. enum auth_stat {
  412.     AUTH_BADCRED      = 1,  /* \fIbad credentials (seal broken) \fP*/
  413.     AUTH_REJECTEDCRED = 2,  /* \fIclient must begin new session \fP*/
  414.     AUTH_BADVERF      = 3,  /* \fIbad verifier (seal broken)    \fP*/
  415.     AUTH_REJECTEDVERF = 4,  /* \fIverifier expired or replayed  \fP*/
  416.     AUTH_TOOWEAK      = 5   /* \fIrejected for security reasons \fP*/
  417. };
  418. X.DE
  419. X.KE
  420. X.ie t .DS
  421. X.el .DS L
  422. X.ft I
  423. /*
  424. * The  RPC  message: 
  425. * All   messages  start with   a transaction  identifier,  xid,
  426. * followed  by a  two-armed  discriminated union.   The union's
  427. * discriminant is a  msg_type which switches to  one of the two
  428. * types   of the message.   The xid  of a \fIREPLY\fP  message always
  429. * matches  that of the initiating \fICALL\fP   message.   NB: The xid
  430. * field is only  used for clients  matching reply messages with
  431. * call messages  or for servers detecting  retransmissions; the
  432. * service side  cannot treat this id  as any type   of sequence
  433. * number.
  434. */
  435. X.ft CW
  436. struct rpc_msg {
  437.     unsigned int xid;
  438.     union switch (msg_type mtype) {
  439.         case CALL:
  440.             call_body cbody;
  441.         case REPLY:  
  442.             reply_body rbody;
  443.     } body;
  444. };
  445. X.DE
  446. X.ie t .DS
  447. X.el .DS L
  448. X.ft I
  449. /*
  450. * Body of an RPC request call: 
  451. * In version 2 of the  RPC protocol specification, rpcvers must
  452. * be equal to 2.  The  fields prog,  vers, and proc specify the
  453. * remote program, its version number, and the  procedure within
  454. * the remote program to be called.  After these  fields are two
  455. * authentication  parameters: cred (authentication credentials)
  456. * and verf  (authentication verifier).  The  two authentication
  457. * parameters are   followed by  the  parameters  to  the remote
  458. * procedure,  which  are specified  by  the  specific   program
  459. * protocol.
  460. */
  461. X.ft CW
  462. struct call_body {
  463.     unsigned int rpcvers;  /* \fImust be equal to two (2) \fP*/
  464.     unsigned int prog;
  465.     unsigned int vers;
  466.     unsigned int proc;
  467.     opaque_auth cred;
  468.     opaque_auth verf;
  469.     /* \fIprocedure specific parameters start here \fP*/
  470. };
  471. X.DE
  472. X.ie t .DS
  473. X.el .DS L
  474. X.ft I
  475. /*
  476. * Body of a reply to an RPC request:
  477. * The call message was either accepted or rejected.
  478. */
  479. X.ft CW
  480. union reply_body switch (reply_stat stat) {
  481.     case MSG_ACCEPTED:  
  482.         accepted_reply areply;
  483.     case MSG_DENIED:  
  484.         rejected_reply rreply;
  485. } reply;
  486. X.DE
  487. X.ie t .DS
  488. X.el .DS L
  489. X.ft I
  490. /*
  491. * Reply to   an RPC request  that  was accepted  by the server:
  492. * there could be an error even though the request was accepted.
  493. * The first field is an authentication verifier that the server
  494. * generates in order to  validate itself  to the caller.  It is
  495. * followed by    a  union whose     discriminant  is   an  enum
  496. * accept_stat.  The  \fISUCCESS\fP  arm of    the union  is  protocol
  497. * specific.  The \fIPROG_UNAVAIL\fP, \fIPROC_UNAVAIL\fP, and \fIGARBAGE_ARGP\fP
  498. * arms of the union are void.   The \fIPROG_MISMATCH\fP arm specifies
  499. * the lowest and highest version numbers of the  remote program
  500. * supported by the server.
  501. */
  502. X.ft CW
  503. struct accepted_reply {
  504.     opaque_auth verf;
  505.     union switch (accept_stat stat) {
  506.         case SUCCESS:
  507.             opaque results[0];
  508.             /* \fIprocedure-specific results start here\fP */
  509.         case PROG_MISMATCH:
  510.             struct {
  511.                 unsigned int low;
  512.                 unsigned int high;
  513.             } mismatch_info;
  514.         default:
  515. X.ft I
  516.             /*
  517.             * Void.  Cases include \fIPROG_UNAVAIL, PROC_UNAVAIL\fP,
  518.             * and \fIGARBAGE_ARGS\fP.
  519.             */
  520. X.ft CW
  521.             void;
  522.     } reply_data;
  523. };
  524. X.DE
  525. X.ie t .DS
  526. X.el .DS L
  527. X.ft I
  528. /*
  529. * Reply to an RPC request that was rejected by the server: 
  530. * The request  can   be rejected for   two reasons:  either the
  531. * server   is not  running a   compatible  version  of the  RPC
  532. * protocol    (\fIRPC_MISMATCH\fP), or    the  server   refuses    to
  533. * authenticate the  caller  (\fIAUTH_ERROR\fP).  In  case of  an  RPC
  534. * version mismatch,  the server returns the  lowest and highest
  535. * supported    RPC  version    numbers.  In   case   of refused
  536. * authentication, failure status is returned.
  537. */
  538. X.ft CW
  539. union rejected_reply switch (reject_stat stat) {
  540.     case RPC_MISMATCH:
  541.         struct {
  542.             unsigned int low;
  543.             unsigned int high;
  544.         } mismatch_info;
  545.     case AUTH_ERROR: 
  546.         auth_stat stat;
  547. };
  548. X.DE
  549. X.NH 1
  550. \&Authentication Protocols
  551. X.LP
  552. As previously stated, authentication parameters are opaque, but
  553. open-ended to the rest of the RPC protocol.  This section defines
  554. some "flavors" of authentication implemented at (and supported by)
  555. Sun.  Other sites are free to invent new authentication types, with
  556. the same rules of flavor number assignment as there is for program
  557. number assignment.
  558. X.NH 2
  559. \&Null Authentication
  560. X.LP
  561. Often calls must be made where the caller does not know who he is or
  562. the server does not care who the caller is.  In this case, the flavor
  563. value (the discriminant of the \fIopaque_auth\fP's union) of the RPC
  564. message's credentials, verifier, and response verifier is
  565. X.I AUTH_NULL .
  566. The  bytes of the opaque_auth's body  are undefined.
  567. It is recommended that the opaque length be zero.
  568. X.NH 2
  569. \&UNIX Authentication
  570. X.LP
  571. The caller of a remote procedure may wish to identify himself as he
  572. is identified on a UNIX system.  The  value of the credential's
  573. discriminant of an RPC call  message is  
  574. X.I AUTH_UNIX .
  575. the credential's opaque body encode the the following structure:
  576. X.DS
  577. X.ft CW
  578. struct auth_unix {
  579.     unsigned int stamp;
  580.     string machinename<255>;
  581.     unsigned int uid;
  582.     unsigned int gid;
  583.     unsigned int gids<10>;
  584. };
  585. X.DE
  586. The 
  587. X.I stamp 
  588. is an  arbitrary    ID which the  caller machine   may
  589. generate.  The 
  590. X.I machinename 
  591. is the  name of the  caller's machine (like  "krypton").  The 
  592. X.I uid 
  593. is  the caller's effective user  ID.  The  
  594. X.I gid 
  595. is  the caller's effective  group  ID.  The 
  596. X.I gids 
  597. is  a
  598. counted array of groups which contain the caller as  a member.  The
  599. verifier accompanying the  credentials  should  be  of  
  600. X.I AUTH_NULL
  601. (defined above).
  602. X.LP
  603. The value of the discriminant of  the response verifier received in
  604. the  reply  message  from  the    server  may   be   
  605. X.I AUTH_NULL 
  606. or
  607. X.I AUTH_SHORT .
  608. In  the  case  of 
  609. X.I AUTH_SHORT ,
  610. the bytes of the response verifier's string encode an opaque
  611. structure.  This new opaque structure may now be passed to the server
  612. instead of the original
  613. X.I AUTH_UNIX
  614. flavor credentials.  The server keeps a cache which maps shorthand
  615. opaque structures (passed back by way of an
  616. X.I AUTH_SHORT
  617. style response verifier) to the original credentials of the caller.
  618. The caller can save network bandwidth and server cpu cycles by using
  619. the new credentials.
  620. X.LP
  621. The server may flush the shorthand opaque structure at any time.  If
  622. this happens, the remote procedure call message will be rejected due
  623. to an authentication error.  The reason for the failure will be
  624. X.I AUTH_REJECTEDCRED .
  625. At this point, the caller may wish to try the original
  626. X.I AUTH_UNIX
  627. style of credentials.
  628. X.KS
  629. X.NH 1
  630. \&Record Marking Standard
  631. X.LP
  632. When RPC messages are passed on top of a byte stream protocol (like
  633. TCP/IP), it is necessary, or at least desirable, to delimit one
  634. message from another in order to detect and possibly recover from
  635. user protocol errors.  This is called record marking (RM).  Sun uses
  636. this RM/TCP/IP transport for passing RPC messages on TCP streams.
  637. One RPC message fits into one RM record.
  638. X.LP
  639. A record is composed of one or more record fragments.  A record
  640. fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
  641. fragment data.  The bytes encode an unsigned binary number; as with
  642. XDR integers, the byte order is from highest to lowest.  The number
  643. encodes two values\(ema boolean which indicates whether the fragment
  644. is the last fragment of the record (bit value 1 implies the fragment
  645. is the last fragment) and a 31-bit unsigned binary value which is the
  646. length in bytes of the fragment's data.  The boolean value is the
  647. highest-order bit of the header; the length is the 31 low-order bits.
  648. (Note that this record specification is NOT in XDR standard form!)
  649. X.KE
  650. X.KS
  651. X.NH 1
  652. \&The RPC Language
  653. X.LP
  654. Just as there was a need to describe the XDR data-types in a formal
  655. language, there is also need to describe the procedures that operate
  656. on these XDR data-types in a formal language as well.  We use the RPC
  657. Language for this purpose.  It is an extension to the XDR language.
  658. The following example is used to describe the essence of the
  659. language.
  660. X.NH 2
  661. \&An Example Service Described in the RPC Language
  662. X.LP
  663. Here is an example of the specification of a simple ping program.
  664. X.ie t .DS
  665. X.el .DS L
  666. X.vs 11
  667. X.ft I
  668. /*
  669. * Simple ping program
  670. */
  671. X.ft CW
  672. program PING_PROG {
  673.     /* \fILatest and greatest version\fP */
  674.     version PING_VERS_PINGBACK {
  675.     void 
  676.     PINGPROC_NULL(void) = 0;
  677.  
  678. X.ft I
  679.     /*
  680.     * Ping the caller, return the round-trip time
  681.     * (in microseconds). Returns -1 if the operation
  682.     * timed out.
  683.     */
  684. X.ft CW
  685.     int
  686.     PINGPROC_PINGBACK(void) = 1;        
  687. } = 2;     
  688.  
  689. X.ft I
  690. /*
  691. * Original version
  692. */
  693. X.ft CW
  694. version PING_VERS_ORIG {
  695.     void 
  696.     PINGPROC_NULL(void) = 0;
  697.     } = 1;
  698. } = 1;
  699.  
  700. const PING_VERS = 2;      /* \fIlatest version \fP*/
  701. X.vs
  702. X.DE
  703. X.KE
  704. X.LP
  705. The first version described is
  706. X.I PING_VERS_PINGBACK
  707. with  two procedures,   
  708. X.I PINGPROC_NULL 
  709. and 
  710. X.I PINGPROC_PINGBACK.
  711. X.I PINGPROC_NULL 
  712. takes no arguments and returns no results, but it is useful for
  713. computing round-trip times from the client to the server and back
  714. again.  By convention, procedure 0 of any RPC protocol should have
  715. the same semantics, and never require any kind of authentication.
  716. The second procedure is used for the client to have the server do a
  717. reverse ping operation back to the client, and it returns the amount
  718. of time (in microseconds) that the operation used.  The next version,
  719. X.I PING_VERS_ORIG ,
  720. is the original version of the protocol
  721. and it does not contain
  722. X.I PINGPROC_PINGBACK
  723. procedure. It  is useful
  724. for compatibility  with old client  programs,  and as  this program
  725. matures it may be dropped from the protocol entirely.
  726. X.KS
  727. X.NH 2
  728. \&The RPC Language Specification
  729. X.LP
  730. The  RPC language is identical to  the XDR language, except for the
  731. added definition of a
  732. X.I program-def 
  733. described below.
  734. X.DS
  735. X.ft CW
  736. program-def:
  737.     "program" identifier "{"
  738.         version-def 
  739.         version-def *
  740.     "}" "=" constant ";"
  741.  
  742. version-def:
  743.     "version" identifier "{"
  744.         procedure-def
  745.         procedure-def *
  746.     "}" "=" constant ";"
  747.  
  748. procedure-def:
  749.     type-specifier identifier "(" type-specifier ")"
  750.     "=" constant ";"
  751. X.DE
  752. X.KE
  753. X.NH 2
  754. \&Syntax Notes
  755. X.IP  1.
  756. The following keywords  are  added  and   cannot  be used   as
  757. identifiers: "program" and "version";
  758. X.IP  2.
  759. A version name cannot occur more than once within the  scope of
  760. a program definition. Nor can a version number occur more than once
  761. within the scope of a program definition.
  762. X.IP  3.
  763. A procedure name cannot occur  more than once within  the scope
  764. of a version definition. Nor can a procedure number occur more than
  765. once within the scope of version definition.
  766. X.IP  4.
  767. Program identifiers are in the same name space as  constant and
  768. type identifiers.
  769. X.IP  5.
  770. Only unsigned constants can  be assigned to programs, versions
  771. and procedures.
  772. X.NH 1
  773. \&Port Mapper Program Protocol
  774. X.LP
  775. The port mapper program maps RPC program and version numbers to
  776. transport-specific port numbers.  This program makes dynamic binding
  777. of remote programs possible.
  778. X.LP
  779. This is desirable because the range of reserved port numbers is very
  780. small and the number of potential remote programs is very large.  By
  781. running only the port mapper on a reserved port, the port numbers of
  782. other remote programs can be ascertained by querying the port mapper.
  783. X.LP
  784. The port mapper also aids in broadcast RPC.  A given RPC program will
  785. usually have different port number bindings on different machines, so
  786. there is no way to directly broadcast to all of these programs.  The
  787. port mapper, however, does have a fixed port number.  So, to
  788. broadcast to a given program, the client actually sends its message
  789. to the port mapper located at the broadcast address.  Each port
  790. mapper that picks up the broadcast then calls the local service
  791. specified by the client.  When the port mapper gets the reply from
  792. the local service, it sends the reply on back to the client.
  793. X.KS
  794. X.NH 2
  795. \&Port Mapper Protocol Specification (in RPC Language)
  796. X.ie t .DS
  797. X.el .DS L
  798. X.ft CW
  799. X.vs 11
  800. const PMAP_PORT = 111;      /* \fIportmapper port number \fP*/
  801.  
  802. X.ft I
  803. /*
  804. * A mapping of (program, version, protocol) to port number
  805. */
  806. X.ft CW
  807. struct mapping {
  808.     unsigned int prog;
  809.     unsigned int vers;
  810.     unsigned int prot;
  811.     unsigned int port;
  812. };
  813.  
  814. X.ft I
  815. /* 
  816. * Supported values for the "prot" field
  817. */
  818. X.ft CW
  819. const IPPROTO_TCP = 6;      /* \fIprotocol number for TCP/IP \fP*/
  820. const IPPROTO_UDP = 17;     /* \fIprotocol number for UDP/IP \fP*/
  821.  
  822. X.ft I
  823. /*
  824. * A list of mappings
  825. */
  826. X.ft CW
  827. struct *pmaplist {
  828.     mapping map;
  829.     pmaplist next;
  830. };
  831. X.vs
  832. X.DE
  833. X.ie t .DS
  834. X.el .DS L
  835. X.vs 11
  836. X.ft I
  837. /*
  838. * Arguments to callit
  839. */
  840. X.ft CW
  841. struct call_args {
  842.     unsigned int prog;
  843.     unsigned int vers;
  844.     unsigned int proc;
  845.     opaque args<>;
  846. };  
  847.  
  848. X.ft I
  849. /*
  850. * Results of callit
  851. */
  852. X.ft CW
  853. struct call_result {
  854.     unsigned int port;
  855.     opaque res<>;
  856. };
  857. X.vs
  858. X.DE
  859. X.KE
  860. X.ie t .DS
  861. X.el .DS L
  862. X.vs 11
  863. X.ft I
  864. /*
  865. * Port mapper procedures
  866. */
  867. X.ft CW
  868. program PMAP_PROG {
  869.     version PMAP_VERS {
  870.         void 
  871.         PMAPPROC_NULL(void)         = 0;
  872.  
  873.         bool
  874.         PMAPPROC_SET(mapping)       = 1;
  875.  
  876.         bool
  877.         PMAPPROC_UNSET(mapping)     = 2;
  878.  
  879.         unsigned int
  880.         PMAPPROC_GETPORT(mapping)   = 3;
  881.  
  882.         pmaplist
  883.         PMAPPROC_DUMP(void)         = 4;
  884.  
  885.         call_result
  886.         PMAPPROC_CALLIT(call_args)  = 5;
  887.     } = 2;
  888. } = 100000;
  889. X.vs
  890. X.DE
  891. X.NH 2
  892. \&Port Mapper Operation
  893. X.LP
  894. The portmapper program currently supports two protocols (UDP/IP and
  895. TCP/IP).  The portmapper is contacted by talking to it on assigned
  896. port number 111 (SUNRPC [8]) on either of these protocols.  The
  897. following is a description of each of the portmapper procedures:
  898. X.IP \fBPMAPPROC_NULL:\fP
  899. This procedure does no work.  By convention, procedure zero of any
  900. protocol takes no parameters and returns no results.
  901. X.IP \fBPMAPPROC_SET:\fP
  902. When a program first becomes available on a machine, it registers
  903. itself with the port mapper program on the same machine.  The program
  904. passes its program number "prog", version number "vers", transport
  905. protocol number "prot", and the port "port" on which it awaits
  906. service request.  The procedure returns a boolean response whose
  907. value is
  908. X.I TRUE
  909. if the procedure successfully established the mapping and 
  910. X.I FALSE 
  911. otherwise.  The procedure refuses to establish
  912. a mapping if one already exists for the tuple "(prog, vers, prot)".
  913. X.IP \fBPMAPPROC_UNSET:\fP
  914. When a program becomes unavailable, it should unregister itself with
  915. the port mapper program on the same machine.  The parameters and
  916. results have meanings identical to those of
  917. X.I PMAPPROC_SET .
  918. The protocol and port number fields of the argument are ignored.
  919. X.IP \fBPMAPPROC_GETPORT:\fP
  920. Given a program number "prog", version number "vers", and transport
  921. protocol number "prot", this procedure returns the port number on
  922. which the program is awaiting call requests.  A port value of zeros
  923. means the program has not been registered.  The "port" field of the
  924. argument is ignored.
  925. X.IP \fBPMAPPROC_DUMP:\fP
  926. This procedure enumerates all entries in the port mapper's database.
  927. The procedure takes no parameters and returns a list of program,
  928. version, protocol, and port values.
  929. X.IP \fBPMAPPROC_CALLIT:\fP
  930. This procedure allows a caller to call another remote procedure on
  931. the same machine without knowing the remote procedure's port number.
  932. It is intended for supporting broadcasts to arbitrary remote programs
  933. via the well-known port mapper's port.  The parameters "prog",
  934. "vers", "proc", and the bytes of "args" are the program number,
  935. version number, procedure number, and parameters of the remote
  936. procedure.
  937. X.LP
  938. X.B Note:
  939. X.RS
  940. X.IP  1.
  941. This procedure only sends a response if the procedure was
  942. successfully executed and is silent (no response) otherwise.
  943. X.IP  2.
  944. The port mapper communicates with the remote program using UDP/IP
  945. only.
  946. X.RE
  947. X.LP
  948. The procedure returns the remote program's port number, and the bytes
  949. of results are the results of the remote procedure.
  950. X.bp
  951. X.NH 1
  952. \&References
  953. X.LP
  954. [1]  Birrell, Andrew D. & Nelson, Bruce Jay; "Implementing Remote
  955. Procedure Calls"; XEROX CSL-83-7, October 1983.
  956. X.LP
  957. [2]  Cheriton, D.; "VMTP:  Versatile Message Transaction Protocol",
  958. Preliminary Version 0.3; Stanford University, January 1987.
  959. X.LP
  960. [3]  Diffie & Hellman; "Net Directions in Cryptography"; IEEE
  961. Transactions on Information Theory IT-22, November 1976.
  962. X.LP
  963. [4]  Harrenstien, K.; "Time Server", RFC 738; Information Sciences
  964. Institute, October 1977.
  965. X.LP
  966. [5]  National Bureau of Standards; "Data Encryption Standard"; Federal
  967. Information Processing Standards Publication 46, January 1977.
  968. X.LP
  969. [6]  Postel, J.; "Transmission Control Protocol - DARPA Internet
  970. Program Protocol Specification", RFC 793; Information Sciences
  971. Institute, September 1981.
  972. X.LP
  973. [7]  Postel, J.; "User Datagram Protocol", RFC 768; Information Sciences
  974. Institute, August 1980.
  975. X.LP
  976. [8]  Reynolds, J.  & Postel, J.; "Assigned Numbers", RFC 923; Information
  977. Sciences Institute, October 1984.
  978. Funky_Stuff
  979. echo x - rpcgen.ms
  980. sed -e 's/^X//' > rpcgen.ms <<'Funky_Stuff'
  981. X.\" @(#)rpcgen.ms    1.2 87/11/09 3.9 RPCSRC
  982. X.de BT
  983. X.if \\n%=1 .tl ''- % -''
  984. X..
  985. X.ND
  986. X.\" prevent excess underlining in nroff
  987. X.if n .fp 2 R
  988. X.OH '\fBrpcgen\fP Programming Guide''Page %'
  989. X.EH 'Page %''\fBrpcgen\fP Programming Guide'
  990. X.if \\n%=1 .bp
  991. X.SH
  992. \&\fBrpcgen\fP Programming Guide
  993. X.NH 0
  994. \&The \fBrpcgen\fP Protocol Compiler
  995. X.IX rpcgen "" \fIrpcgen\fP "" PAGE MAJOR
  996. X.LP
  997. X.IX RPC "" "" \fIrpcgen\fP
  998. The details of programming applications to use Remote Procedure Calls 
  999. can be overwhelming.  Perhaps most daunting is the writing of the XDR 
  1000. routines necessary to convert procedure arguments and results into 
  1001. their network format and vice-versa.  
  1002. X.LP
  1003. Fortunately, 
  1004. X.I rpcgen 
  1005. exists to help programmers write RPC applications simply and directly.
  1006. X.I rpcgen 
  1007. does most of the dirty work, allowing programmers to debug 
  1008. the  main  features of their application, instead of requiring them to
  1009. spend most of their time debugging their network interface code.
  1010. X.LP
  1011. X.I rpcgen 
  1012. is a  compiler.  It accepts a remote program interface definition written
  1013. in a language, called RPC Language, which is similar to C.  It produces a C
  1014. language output which includes stub versions of the client routines, a
  1015. server skeleton, XDR filter routines for both parameters and results, and a
  1016. header file that contains common definitions. The client stubs interface
  1017. with the RPC library and effectively hide the network from their callers.
  1018. The server stub similarly hides the network from the server procedures that
  1019. are to be invoked by remote clients.
  1020. X.I rpcgen 's
  1021. output files can be compiled and linked in the usual way.  The developer
  1022. writes server procedures\(emin any language that observes Sun calling
  1023. conventions\(emand links them with the server skeleton produced by
  1024. X.I rpcgen 
  1025. to get an executable server program.  To use a remote program, a programmer
  1026. writes an ordinary main program that makes local procedure calls to the 
  1027. client stubs produced by
  1028. X.I rpcgen .
  1029. Linking this program with 
  1030. X.I rpcgen 's
  1031. stubs creates an executable program.  (At present the main program must be 
  1032. written in C).
  1033. X.I rpcgen 
  1034. options can be used to suppress stub generation and to specify the transport
  1035. to be used by the server stub.
  1036. X.LP
  1037. Like all compilers, 
  1038. X.I rpcgen 
  1039. reduces development time
  1040. that would otherwise be spent coding and debugging low-level routines.
  1041. All compilers, including 
  1042. X.I rpcgen ,
  1043. do this at a small cost in efficiency
  1044. and flexibility.  However,   many compilers allow  escape  hatches for
  1045. programmers to  mix low-level code with  high-level code. 
  1046. X.I rpcgen 
  1047. is no exception.  In speed-critical applications, hand-written routines 
  1048. can be linked with the 
  1049. X.I rpcgen 
  1050. output without any difficulty.  Also, one may proceed by using
  1051. X.I rpcgen 
  1052. output as a starting point, and rewriting it as necessary.
  1053. X.NH 1
  1054. \&Converting Local Procedures into Remote Procedures
  1055. X.IX rpcgen "local procedures" \fIrpcgen\fP
  1056. X.IX rpcgen "remote procedures" \fIrpcgen\fP
  1057. X.LP
  1058. Assume an application that runs on a single machine, one which we want 
  1059. to convert to run over the network.  Here we will demonstrate such a 
  1060. conversion by way of a simple example\(ema program that prints a 
  1061. message to the console:
  1062. X.ie t .DS
  1063. X.el .DS L
  1064. X.ft I
  1065. /*
  1066.  * printmsg.c: print a message on the console
  1067.  */
  1068. X.ft CW
  1069. #include <stdio.h>
  1070.  
  1071. main(argc, argv)
  1072.     int argc;
  1073.     char *argv[];
  1074. {
  1075.     char *message;
  1076.  
  1077.     if (argc < 2) {
  1078.         fprintf(stderr, "usage: %s <message>\en", argv[0]);
  1079.         exit(1);
  1080.     }
  1081.     message = argv[1];
  1082.  
  1083.     if (!printmessage(message)) {
  1084.         fprintf(stderr, "%s: couldn't print your message\en",
  1085.             argv[0]);
  1086.         exit(1);
  1087.     } 
  1088.     printf("Message delivered!\n");
  1089. }
  1090. X.ft I
  1091. /*
  1092.  * Print a message to the console.
  1093.  * Return a boolean indicating whether the message was actually printed.
  1094.  */
  1095. X.ft CW
  1096. printmessage(msg)
  1097.     char *msg;
  1098. {
  1099.     FILE *f;
  1100.  
  1101.     f = fopen("/dev/console", "w");
  1102.     if (f == NULL) {
  1103.         return (0);
  1104.     }
  1105.     fprintf(f, "%s\en", msg);
  1106.     fclose(f);
  1107.     return(1);
  1108. }
  1109. X.DE
  1110. X.LP
  1111. And then, of course:
  1112. X.ie t .DS
  1113. X.el .DS L
  1114. X.ft CW
  1115. example%  \fBcc printmsg.c -o printmsg\fP
  1116. example%  \fBprintmsg "Hello, there."\fP
  1117. Message delivered!
  1118. example%
  1119. X.DE
  1120. X.LP
  1121. If  
  1122. X.I printmessage 
  1123. was turned into  a remote procedure,
  1124. then it could be  called from anywhere in   the network.  
  1125. Ideally,  one would just  like to stick   a  keyword like  
  1126. X.I remote 
  1127. in  front  of a
  1128. procedure to turn it into a  remote procedure.  Unfortunately,
  1129. we  have to live  within the  constraints of  the   C language, since 
  1130. it existed   long before  RPC did.  But   even without language 
  1131. support, it's not very difficult to make a procedure remote.
  1132. X.LP
  1133. In  general, it's necessary to figure  out  what the types are for
  1134. all procedure inputs and outputs.  In  this case,   we  have a 
  1135. procedure
  1136. X.I printmessage 
  1137. which takes a  string as input, and returns  an integer
  1138. as output.  Knowing  this, we can write a  protocol specification in RPC
  1139. language that  describes the remote  version of 
  1140. X.I printmessage .
  1141. Here it is:
  1142. X.ie t .DS
  1143. X.el .DS L
  1144. X.ft I
  1145. /*
  1146.  * msg.x: Remote message printing protocol
  1147.  */
  1148. X.ft CW
  1149.  
  1150. program MESSAGEPROG {
  1151.     version MESSAGEVERS {
  1152.         int PRINTMESSAGE(string) = 1;
  1153.     } = 1;
  1154. } = 99;
  1155. X.DE
  1156. X.LP
  1157. Remote procedures are part of remote programs, so we actually declared
  1158. an  entire  remote program  here  which contains  the single procedure
  1159. X.I PRINTMESSAGE .
  1160. This procedure was declared to be  in version  1 of the
  1161. remote program.  No null procedure (procedure 0) is necessary because
  1162. X.I rpcgen 
  1163. generates it automatically.
  1164. X.LP
  1165. Notice that everything is declared with all capital  letters.  This is
  1166. not required, but is a good convention to follow.
  1167. X.LP
  1168. Notice also that the argument type is "string" and not "char *".  This
  1169. is because a "char *" in C is ambiguous. Programmers usually intend it
  1170. to mean  a null-terminated string   of characters, but  it  could also
  1171. represent a pointer to a single character or a  pointer to an array of
  1172. characters.  In  RPC language,  a  null-terminated  string is 
  1173. unambiguously called a "string". 
  1174. X.LP
  1175. There are  just two more things to  write.  First, there is the remote
  1176. procedure itself.  Here's the definition of a remote procedure
  1177. to implement the
  1178. X.I PRINTMESSAGE
  1179. procedure we declared above:
  1180. X.ie t .DS
  1181. X.el .DS L
  1182. X.vs 11
  1183. X.ft I
  1184. /*
  1185.  * msg_proc.c: implementation of the remote procedure "printmessage"
  1186.  */
  1187. X.ft CW
  1188.  
  1189. #include <stdio.h>
  1190. #include <rpc/rpc.h>    /* \fIalways needed\fP  */
  1191. #include "msg.h"        /* \fIneed this too: msg.h will be generated by rpcgen\fP */
  1192.  
  1193. X.ft I
  1194. /*
  1195.  * Remote verson of "printmessage"
  1196.  */
  1197. X.ft CW
  1198. int *
  1199. printmessage_1(msg)
  1200.     char **msg;
  1201. {
  1202.     static int result;  /* \fImust be static!\fP */
  1203.     FILE *f;
  1204.  
  1205.     f = fopen("/dev/console", "w");
  1206.     if (f == NULL) {
  1207.         result = 0;
  1208.         return (&result);
  1209.     }
  1210.     fprintf(f, "%s\en", *msg);
  1211.     fclose(f);
  1212.     result = 1;
  1213.     return (&result);
  1214. }
  1215. X.vs
  1216. X.DE
  1217. X.LP
  1218. Notice here that the declaration of the remote procedure
  1219. X.I printmessage_1 
  1220. differs from that of the local procedure
  1221. X.I printmessage 
  1222. in three ways:
  1223. X.IP  1.
  1224. It takes a pointer to a string instead of a string itself.  This
  1225. is true of all  remote procedures:  they always take pointers to  their
  1226. arguments rather than the arguments themselves.
  1227. X.IP  2.
  1228. It returns a pointer to an  integer instead of  an integer itself. This is
  1229. also generally true of remote procedures: they always return a pointer
  1230. to their results.
  1231. X.IP  3.
  1232. It has  an "_1" appended to  its name.   In  general, all  remote
  1233. procedures called by 
  1234. X.I rpcgen 
  1235. are named by  the following rule: the name in the program  definition  
  1236. (here 
  1237. X.I PRINTMESSAGE )
  1238. is converted   to all
  1239. lower-case   letters, an underbar ("_")   is appended  to it, and
  1240. finally the version number (here 1) is appended.
  1241. X.LP
  1242. The last thing to do is declare the main client program that will call
  1243. the remote procedure. Here it is:
  1244. X.ie t .DS
  1245. X.el .DS L
  1246. X.ft I
  1247. /*
  1248.  * rprintmsg.c: remote version of "printmsg.c"
  1249.  */
  1250. X.ft CW
  1251. #include <stdio.h>
  1252. #include <rpc/rpc.h>     /* \fIalways needed\fP  */
  1253. #include "msg.h"         /* \fIneed this too: msg.h will be generated by rpcgen\fP */
  1254.  
  1255. main(argc, argv)
  1256.     int argc;
  1257.     char *argv[];
  1258. {
  1259.     CLIENT *cl;
  1260.     int *result;
  1261.     char *server;
  1262.     char *message;
  1263.  
  1264.     if (argc < 3) {
  1265.         fprintf(stderr, "usage: %s host message\en", argv[0]);
  1266.         exit(1);
  1267.     }
  1268.  
  1269. X.ft I
  1270.     /*
  1271.      * Save values of command line arguments 
  1272.      */
  1273. X.ft CW
  1274.     server = argv[1];
  1275.     message = argv[2];
  1276.  
  1277. X.ft I
  1278.     /*
  1279.      * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
  1280.      * server designated on the command line. We tell the RPC package
  1281.      * to use the "tcp" protocol when contacting the server.
  1282.      */
  1283. X.ft CW
  1284.     cl = clnt_create(server, MESSAGEPROG, MESSAGEVERS, "tcp");
  1285.     if (cl == NULL) {
  1286. X.ft I
  1287.         /*
  1288.          * Couldn't establish connection with server.
  1289.          * Print error message and die.
  1290.          */
  1291. X.ft CW
  1292.         clnt_pcreateerror(server);
  1293.         exit(1);
  1294.     }
  1295.     
  1296. X.ft I
  1297.     /*
  1298.      * Call the remote procedure "printmessage" on the server
  1299.      */
  1300. X.ft CW
  1301.     result = printmessage_1(&message, cl);
  1302.     if (result == NULL) {
  1303. X.ft I
  1304.         /*
  1305.          * An error occurred while calling the server. 
  1306.           * Print error message and die.
  1307.          */
  1308. X.ft CW
  1309.         clnt_perror(cl, server);
  1310.         exit(1);
  1311.     }
  1312.  
  1313. X.ft I
  1314.     /*
  1315.      * Okay, we successfully called the remote procedure.
  1316.      */
  1317. X.ft CW
  1318.     if (*result == 0) {
  1319. X.ft I
  1320.         /*
  1321.          * Server was unable to print our message. 
  1322.          * Print error message and die.
  1323.          */
  1324. X.ft CW
  1325.         fprintf(stderr, "%s: %s couldn't print your message\en", 
  1326.             argv[0], server);    
  1327.         exit(1);
  1328.     } 
  1329.  
  1330. X.ft I
  1331.     /*
  1332.      * The message got printed on the server's console
  1333.      */
  1334. X.ft CW
  1335.     printf("Message delivered to %s!\en", server);
  1336. }
  1337. X.DE
  1338. There are two things to note here:
  1339. X.IP  1.
  1340. X.IX "client handle"
  1341. First a client "handle" is created  using the RPC library routine
  1342. X.I clnt_create .
  1343. This client handle will be passed  to the stub routines
  1344. which call the remote procedure.
  1345. X.IP  2.
  1346. The remote procedure  
  1347. X.I printmessage_1 
  1348. is called exactly  the same way as it is  declared in 
  1349. X.I msg_proc.c 
  1350. except for the inserted client handle as the first argument.
  1351. X.LP
  1352. Here's how to put all of the pieces together:
  1353. X.ie t .DS
  1354. X.el .DS L
  1355. X.ft CW
  1356. example%  \fBrpcgen msg.x\fP
  1357. example%  \fBcc rprintmsg.c msg_clnt.c -o rprintmsg\fP
  1358. example%  \fBcc msg_proc.c msg_svc.c -o msg_server\fP
  1359. X.DE
  1360. Two programs were compiled here: the client program 
  1361. X.I printmsg 
  1362. and the server  program 
  1363. X.I msg_server .
  1364. Before doing this  though,  
  1365. X.I rpcgen 
  1366. was used to fill in the missing pieces.  
  1367. X.LP
  1368. Here is what 
  1369. X.I rpcgen 
  1370. did with the input file 
  1371. X.I msg.x :
  1372. X.IP  1.
  1373. It created a header file called 
  1374. X.I msg.h 
  1375. that contained \fI#define\fP's for
  1376. X.I MESSAGEPROG ,
  1377. X.I MESSAGEVERS 
  1378. and    
  1379. X.I PRINTMESSAGE 
  1380. for use in  the  other modules.
  1381. X.IP  2.
  1382. It created client "stub" routines in the 
  1383. X.I msg_clnt.c 
  1384. file.   In this case there is only one, the 
  1385. X.I printmessage_1 
  1386. that was referred to from the
  1387. X.I printmsg 
  1388. client program.  The name  of the output file for
  1389. client stub routines is always formed in this way:  if the name of the
  1390. input file is  
  1391. X.I FOO.x ,
  1392. the   client  stubs   output file is    called
  1393. X.I FOO_clnt.c .
  1394. X.IP  3.
  1395. It created  the  server   program which calls   
  1396. X.I printmessage_1 
  1397. in
  1398. X.I msg_proc.c .
  1399. This server program is named  
  1400. X.I msg_svc.c .
  1401. The rule for naming the server output file is similar  to the 
  1402. previous one:  for an input  file   called  
  1403. X.I FOO.x ,
  1404. the   output   server   file is  named
  1405. X.I FOO_svc.c .
  1406. X.LP
  1407. Now we're ready to have some fun.  First, copy the server to a
  1408. remote machine and run it.  For this  example,  the
  1409. machine is called "moon".  Server processes are run in the 
  1410. background, because they never exit.
  1411. X.ie t .DS
  1412. X.el .DS L
  1413. X.ft CW
  1414. moon% msg_server &           
  1415. X.DE
  1416. Then on our local machine ("sun") we can print a message on "moon"s 
  1417. console.
  1418. X.ie t .DS
  1419. X.el .DS L
  1420. X.ft CW
  1421. sun% printmsg moon "Hello, moon."
  1422. X.DE
  1423. The message will   get printed to  "moon"s  console. You  can print  a
  1424. message on anybody's console (including your own) with this program if
  1425. you are able to copy the server to their machine and run it.
  1426. X.NH 1
  1427. \&Generating XDR Routines
  1428. X.IX RPC "generating XDR routines"
  1429. X.LP
  1430. The previous example  only demonstrated  the  automatic generation of
  1431. client  and server RPC  code. 
  1432. X.I rpcgen 
  1433. may also  be used to generate XDR routines, that  is,  the routines
  1434. necessary to  convert   local  data
  1435. structures into network format and vice-versa.  This example presents
  1436. a complete RPC service\(ema remote directory listing service, which uses
  1437. X.I rpcgen
  1438. not  only  to generate stub routines, but also to  generate  the XDR
  1439. routines.  Here is the protocol description file:
  1440. X.ie t .DS
  1441. X.el .DS L
  1442. X.ft I
  1443. /*
  1444.  * dir.x: Remote directory listing protocol
  1445.  */
  1446. X.ft CW
  1447. const MAXNAMELEN = 255;        /* \fImaximum length of a directory entry\fP */
  1448.  
  1449. typedef string nametype<MAXNAMELEN>;    /* \fIa directory entry\fP */
  1450.  
  1451. typedef struct namenode *namelist;        /* \fIa link in the listing\fP */
  1452.  
  1453. X.ft I
  1454. /*
  1455.  * A node in the directory listing
  1456.  */
  1457. X.ft CW
  1458. struct namenode {
  1459.     nametype name;        /* \fIname of directory entry\fP */
  1460.     namelist next;        /* \fInext entry\fP */
  1461. };
  1462.  
  1463. X.ft I
  1464. /*
  1465.  * The result of a READDIR operation.
  1466.  */
  1467. X.ft CW
  1468. union readdir_res switch (int errno) {
  1469. case 0:
  1470.     namelist list;    /* \fIno error: return directory listing\fP */
  1471. default:
  1472.     void;        /* \fIerror occurred: nothing else to return\fP */
  1473. };
  1474.  
  1475. X.ft I
  1476. /*
  1477.  * The directory program definition
  1478.  */
  1479. X.ft CW
  1480. program DIRPROG {
  1481.     version DIRVERS {
  1482.         readdir_res
  1483.         READDIR(nametype) = 1;
  1484.     } = 1;
  1485. } = 76;
  1486. X.DE
  1487. Running 
  1488. X.I rpcgen 
  1489. on 
  1490. X.I dir.x 
  1491. creates four output files. Three are the same
  1492. as before: header file, client stub routines  and server skeleton. The
  1493. fourth are the XDR routines necessary for converting the data types we
  1494. declared into XDR format and vice-versa. These are  output in the file
  1495. X.I dir_xdr.c .
  1496. X.LP
  1497. Here is the implementation of the "READDIR" procedure:
  1498. X.ie t .DS
  1499. X.el .DS L
  1500. X.vs 11
  1501. X.ft I
  1502. /*
  1503.  * dir_proc.c: remote readdir implementation
  1504.  */
  1505. X.ft CW
  1506. #include <rpc/rpc.h>
  1507. #include <sys/dir.h>
  1508. #include "dir.h"
  1509.  
  1510. extern int errno;
  1511. extern char *malloc();
  1512. extern char *strdup();
  1513.  
  1514. readdir_res *
  1515. readdir_1(dirname)
  1516.     nametype *dirname;
  1517. {
  1518.     DIR *dirp;
  1519.     struct direct *d;
  1520.     namelist nl;
  1521.     namelist *nlp;
  1522.     static readdir_res res; /* \fImust be static\fP! */
  1523.     
  1524. X.ft I
  1525.     /*
  1526.      * Open directory
  1527.      */
  1528. X.ft CW
  1529.     dirp = opendir(*dirname);
  1530.     if (dirp == NULL) {
  1531.         res.errno = errno;
  1532.         return (&res);
  1533.     }
  1534.  
  1535. X.ft I
  1536.     /*
  1537.      * Free previous result
  1538.      */
  1539. X.ft CW
  1540.     xdr_free(xdr_readdir_res, &res);
  1541.  
  1542. X.ft I
  1543.     /*
  1544.      * Collect directory entries
  1545.      */
  1546. X.ft CW
  1547.     nlp = &res.readdir_res_u.list;
  1548.     while (d = readdir(dirp)) {
  1549.         nl = *nlp = (namenode *) malloc(sizeof(namenode));
  1550.         nl->name = strdup(d->d_name);
  1551.         nlp = &nl->next;
  1552.     }
  1553.     *nlp = NULL;
  1554.  
  1555. X.ft I
  1556.     /*
  1557.      * Return the result
  1558.      */
  1559. X.ft CW
  1560.     res.errno = 0;
  1561.     closedir(dirp);
  1562.     return (&res);
  1563. }
  1564. X.vs
  1565. X.DE
  1566. Finally, there is the client side program to call the server:
  1567. X.ie t .DS
  1568. X.el .DS L
  1569. X.ft I
  1570. /*
  1571.  * rls.c: Remote directory listing client
  1572.  */
  1573. X.ft CW
  1574. #include <stdio.h>
  1575. #include <rpc/rpc.h>    /* \fIalways need this\fP */
  1576. #include "dir.h"        /* \fIneed this too: will be generated by rpcgen\fP */
  1577.  
  1578. extern int errno;
  1579.  
  1580. main(argc, argv)
  1581.     int argc;
  1582.     char *argv[];
  1583. {
  1584.     CLIENT *cl;
  1585.     char *server;
  1586.     char *dir;
  1587.     readdir_res *result;
  1588.     namelist nl;
  1589.     
  1590.  
  1591.     if (argc != 3) {
  1592.         fprintf(stderr, "usage: %s host directory\en", argv[0]);
  1593.         exit(1);
  1594.     }
  1595.  
  1596. X.ft I
  1597.     /*
  1598.      * Remember what our command line arguments refer to
  1599.      */
  1600. X.ft CW
  1601.     server = argv[1];
  1602.     dir = argv[2];
  1603.  
  1604. X.ft I
  1605.     /*
  1606.      * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
  1607.      * server designated on the command line. We tell the RPC package
  1608.      * to use the "tcp" protocol when contacting the server.
  1609.      */
  1610. X.ft CW
  1611.     cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");
  1612.     if (cl == NULL) {
  1613. X.ft I
  1614.         /*
  1615.          * Couldn't establish connection with server.
  1616.          * Print error message and die.
  1617.          */
  1618. X.ft CW
  1619.         clnt_pcreateerror(server);
  1620.         exit(1);
  1621.     }
  1622.     
  1623. X.ft I
  1624.     /*
  1625.      * Call the remote procedure \fIreaddir\fP on the server
  1626.      */
  1627. X.ft CW
  1628.     result = readdir_1(&dir, cl);
  1629.     if (result == NULL) {
  1630. X.ft I
  1631.         /*
  1632.          * An error occurred while calling the server. 
  1633.           * Print error message and die.
  1634.          */
  1635. X.ft CW
  1636.         clnt_perror(cl, server);
  1637.         exit(1);
  1638.     }
  1639.  
  1640. X.ft I
  1641.     /*
  1642.      * Okay, we successfully called the remote procedure.
  1643.      */
  1644. X.ft CW
  1645.     if (result->errno != 0) {
  1646. X.ft I
  1647.         /*
  1648.          * A remote system error occurred.
  1649.          * Print error message and die.
  1650.          */
  1651. X.ft CW
  1652.         errno = result->errno;
  1653.         perror(dir);
  1654.         exit(1);
  1655.     }
  1656.  
  1657. X.ft I
  1658.     /*
  1659.      * Successfully got a directory listing.
  1660.      * Print it out.
  1661.      */
  1662. X.ft CW
  1663.     for (nl = result->readdir_res_u.list; nl != NULL; 
  1664.       nl = nl->next) {
  1665.         printf("%s\n", nl->name);
  1666.     }
  1667. }
  1668. X.DE
  1669. Compile everything, and run.
  1670. X.DS
  1671. X.ft CW
  1672. sun%  \fBrpcgen dir.x\fP
  1673. sun%  \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fP
  1674. sun%  \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fP
  1675.  
  1676. sun%  \fBdir_svc &\fP
  1677.  
  1678. moon%  \fBrls sun /usr/pub\fP
  1679. \&.
  1680. \&..
  1681. ascii
  1682. eqnchar
  1683. greek
  1684. kbd
  1685. marg8
  1686. tabclr
  1687. tabs
  1688. tabs4
  1689. moon%
  1690. X.DE
  1691. X.LP
  1692. X.IX debugging rpcgen "" \fIrpcgen\fP
  1693. A final note about 
  1694. X.I rpcgen :
  1695. The client program and the server procedure can be tested together 
  1696. as a single program by simply linking them with each other rather 
  1697. than with the client and server stubs.  The procedure calls will be
  1698. executed as ordinary local procedure calls and the program can be 
  1699. debugged with a local debugger such as 
  1700. X.I dbx .
  1701. When the program is working, the client program can be linked to 
  1702. the client stub produced by 
  1703. X.I rpcgen 
  1704. and the server procedures can be linked to the server stub produced
  1705. by 
  1706. X.I rpcgen .
  1707. X.SH
  1708. X.I NOTE :
  1709. \fIIf you do this, you may want to comment out calls to RPC library
  1710. routines, and have client-side routines call server routines
  1711. directly.\fP
  1712. X.LP
  1713. X.NH 1
  1714. \&The C-Preprocessor
  1715. X.IX rpcgen "C-preprocessor" \fIrpcgen\fP
  1716. X.LP
  1717. The C-preprocessor is  run on all input  files before they are
  1718. compiled, so all the preprocessor  directives are legal within a  ".x"
  1719. file. Four symbols may be defined, depending upon which output file is
  1720. getting generated. The symbols are:
  1721. X.TS
  1722. box tab (&);
  1723. lfI lfI
  1724. lfL l .
  1725. Symbol&Usage
  1726. _
  1727. RPC_HDR&for header-file output
  1728. RPC_XDR&for XDR routine output
  1729. RPC_SVC&for server-skeleton output
  1730. RPC_CLNT&for client stub output
  1731. X.TE
  1732. X.LP
  1733. Also, 
  1734. X.I rpcgen 
  1735. does  a little preprocessing   of its own. Any  line that
  1736. begins  with  a percent sign is passed  directly into the output file,
  1737. without any interpretation of the line.  Here is a simple example that
  1738. demonstrates the preprocessing features.
  1739. X.ie t .DS
  1740. X.el .DS L
  1741. X.ft I
  1742. /*
  1743.  * time.x: Remote time protocol
  1744.  */
  1745. X.ft CW
  1746. program TIMEPROG {
  1747.         version TIMEVERS {
  1748.                 unsigned int TIMEGET(void) = 1;
  1749.         } = 1;
  1750. } = 44;
  1751.  
  1752. #ifdef RPC_SVC
  1753. %int *
  1754. %timeget_1()
  1755. %{
  1756. %        static int thetime;
  1757. %
  1758. %        thetime = time(0);
  1759. %        return (&thetime);
  1760. %}
  1761. #endif
  1762. X.DE
  1763. The '%' feature is not generally recommended, as there is no guarantee
  1764. that the compiler will stick the output where you intended.
  1765. X.NH 1
  1766. \&RPC Language
  1767. X.IX RPCL
  1768. X.IX rpcgen "RPC Language" \fIrpcgen\fP
  1769. X.LP
  1770. RPC language is an extension of XDR  language.   The sole extension is
  1771. the addition of the
  1772. X.I program 
  1773. type.  For a complete description of the XDR language syntax, see the
  1774. \fIeXternal Data Representation Standard: Protocol Specification\fP
  1775. chapter.  For a description of the RPC extensions to the XDR language,
  1776. see the
  1777. \fIRemote Procedure Calls: Protocol Specification\fP
  1778. chapter.
  1779. X.LP
  1780. However, XDR language is so close to C that if you know C, you know most
  1781. of it already.  We describe here  the syntax of the RPC language,
  1782. showing a  few examples along the way.   We also show how  the various
  1783. RPC and XDR type definitions get  compiled into C  type definitions in
  1784. the output header file.
  1785. X.KS
  1786. X.NH 2
  1787. \&Definitions
  1788. X.IX rpcgen definitions \fIrpcgen\fP
  1789. X.LP
  1790. An RPC language file consists of a series of definitions.
  1791. X.DS L
  1792. X.ft CW
  1793.     definition-list:
  1794.         definition ";"
  1795.         definition ";" definition-list
  1796. X.DE
  1797. X.KE
  1798. It recognizes five types of definitions. 
  1799. X.DS L
  1800. X.ft CW
  1801.     definition:
  1802.         enum-definition
  1803.         struct-definition
  1804.         union-definition
  1805.         typedef-definition
  1806.         const-definition
  1807.         program-definition
  1808. X.DE
  1809. X.NH 2
  1810. \&Structures
  1811. X.IX rpcgen structures \fIrpcgen\fP
  1812. X.LP
  1813. An XDR struct  is declared almost exactly like  its C counterpart.  It
  1814. looks like the following:
  1815. X.DS L
  1816. X.ft CW
  1817.     struct-definition:
  1818.         "struct" struct-ident "{"
  1819.             declaration-list
  1820.         "}"
  1821.  
  1822.     declaration-list:
  1823.         declaration ";"
  1824.         declaration ";" declaration-list
  1825. X.DE
  1826. As  an example, here is an  XDR structure to define  a two-dimensional
  1827. coordinate, and the C structure  that it  gets compiled into  in the
  1828. output header file.
  1829. X.DS
  1830. X.ft CW
  1831.    struct coord {             struct coord {
  1832.         int x;       -->           int x;
  1833.         int y;                     int y;
  1834.    };                         };
  1835.                               typedef struct coord coord;
  1836. X.DE
  1837. The output is identical to the  input, except  for the added
  1838. X.I typedef
  1839. at the end of  the output. This allows  one to use "coord" instead  of
  1840. "struct coord" when declaring items.
  1841. X.NH 2
  1842. \&Unions
  1843. X.IX rpcgen unions \fIrpcgen\fP
  1844. X.LP
  1845. XDR unions are discriminated unions, and look quite different from C
  1846. unions. They are more analogous to  Pascal variant records than they
  1847. are to C unions.
  1848. X.DS L
  1849. X.ft CW
  1850.     union-definition:
  1851.         "union" union-ident "switch" "(" declaration ")" "{"
  1852.             case-list
  1853.         "}"
  1854.  
  1855.     case-list:
  1856.         "case" value ":" declaration ";"
  1857.         "default" ":" declaration ";"
  1858.         "case" value ":" declaration ";" case-list
  1859. X.DE
  1860. Here is an example of a type that might be returned as the result of a
  1861. "read data" operation.  If there is no  error, return a block of data.
  1862. Otherwise, don't return anything.
  1863. X.DS L
  1864. X.ft CW
  1865.     union read_result switch (int errno) {
  1866.     case 0:
  1867.         opaque data[1024];
  1868.     default:
  1869.         void;
  1870.     };
  1871. X.DE
  1872. It gets compiled into the following:
  1873. X.DS L
  1874. X.ft CW
  1875.     struct read_result {
  1876.         int errno;
  1877.         union {
  1878.             char data[1024];
  1879.         } read_result_u;
  1880.     };
  1881.     typedef struct read_result read_result;
  1882. X.DE
  1883. Notice that the union component of the  output struct  has the name as
  1884. the type name, except for the trailing "_u".
  1885. X.NH 2
  1886. \&Enumerations
  1887. X.IX rpcgen enumerations \fIrpcgen\fP
  1888. X.LP
  1889. XDR enumerations have the same syntax as C enumerations.
  1890. X.DS L
  1891. X.ft CW
  1892.     enum-definition:
  1893.         "enum" enum-ident "{"
  1894.             enum-value-list
  1895.         "}"
  1896.  
  1897.     enum-value-list:
  1898.         enum-value
  1899.         enum-value "," enum-value-list
  1900.  
  1901.     enum-value:
  1902.         enum-value-ident 
  1903.         enum-value-ident "=" value
  1904. X.DE
  1905. Here is a short example of  an XDR enum,  and the C enum that  it gets
  1906. compiled into.
  1907. X.DS L
  1908. X.ft CW
  1909.      enum colortype {      enum colortype {
  1910.           RED = 0,              RED = 0,
  1911.           GREEN = 1,   -->      GREEN = 1,
  1912.           BLUE = 2              BLUE = 2,
  1913.      };                    };
  1914.                            typedef enum colortype colortype;
  1915. X.DE
  1916. X.NH 2
  1917. \&Typedef
  1918. X.IX rpcgen typedef \fIrpcgen\fP
  1919. X.LP
  1920. XDR typedefs have the same syntax as C typedefs.
  1921. X.DS L
  1922. X.ft CW
  1923.     typedef-definition:
  1924.         "typedef" declaration
  1925. X.DE
  1926. Here  is an example  that defines a  
  1927. X.I fname_type 
  1928. used  for declaring
  1929. file name strings that have a maximum length of 255 characters.
  1930. X.DS L
  1931. X.ft CW
  1932.     typedef string fname_type<255>; --> typedef char *fname_type;
  1933. X.DE
  1934. X.NH 2
  1935. \&Constants
  1936. X.IX rpcgen constants \fIrpcgen\fP
  1937. X.LP
  1938. XDR constants  symbolic constants  that may be  used wherever  a
  1939. integer constant is used, for example, in array size specifications.
  1940. X.DS L
  1941. X.ft CW
  1942.     const-definition:
  1943.         "const" const-ident "=" integer
  1944. X.DE
  1945. For example, the following defines a constant
  1946. X.I DOZEN 
  1947. equal to 12.
  1948. X.DS L
  1949. X.ft CW
  1950.     const DOZEN = 12;  -->  #define DOZEN 12
  1951. X.DE
  1952. X.NH 2
  1953. \&Programs
  1954. X.IX rpcgen programs \fIrpcgen\fP
  1955. X.LP
  1956. RPC programs are declared using the following syntax:
  1957. X.DS L
  1958. X.ft CW
  1959.     program-definition:
  1960.         "program" program-ident "{" 
  1961.             version-list
  1962.         "}" "=" value 
  1963.  
  1964.     version-list:
  1965.         version ";"
  1966.         version ";" version-list
  1967.  
  1968.     version:
  1969.         "version" version-ident "{"
  1970.             procedure-list 
  1971.         "}" "=" value
  1972.  
  1973.     procedure-list:
  1974.         procedure ";"
  1975.         procedure ";" procedure-list
  1976.  
  1977.     procedure:
  1978.         type-ident procedure-ident "(" type-ident ")" "=" value
  1979. X.DE
  1980. For example, here is the time protocol, revisited:
  1981. X.ie t .DS
  1982. X.el .DS L
  1983. X.ft I
  1984. /*
  1985.  * time.x: Get or set the time. Time is represented as number of seconds
  1986.  * since 0:00, January 1, 1970.
  1987.  */
  1988. X.ft CW
  1989. program TIMEPROG {
  1990.     version TIMEVERS {
  1991.         unsigned int TIMEGET(void) = 1;
  1992.         void TIMESET(unsigned) = 2;
  1993.     } = 1;
  1994. } = 44;        
  1995. X.DE
  1996. This file compiles into #defines in the output header file:
  1997. X.ie t .DS
  1998. X.el .DS L
  1999. X.ft CW
  2000. #define TIMEPROG 44
  2001. #define TIMEVERS 1
  2002. #define TIMEGET 1
  2003. #define TIMESET 2
  2004. X.DE
  2005. X.NH 2
  2006. \&Declarations
  2007. X.IX rpcgen declarations \fIrpcgen\fP
  2008. X.LP
  2009. In XDR, there are only four kinds of declarations.  
  2010. X.DS L
  2011. X.ft CW
  2012.     declaration:
  2013.         simple-declaration
  2014.         fixed-array-declaration
  2015.         variable-array-declaration
  2016.         pointer-declaration
  2017. X.DE
  2018. \fB1) Simple declarations\fP are just like simple C declarations.
  2019. X.DS L
  2020. X.ft CW
  2021.     simple-declaration:
  2022.         type-ident variable-ident
  2023. X.DE
  2024. Example:
  2025. X.DS L
  2026. X.ft CW
  2027.     colortype color;    --> colortype color;
  2028. X.DE
  2029. \fB2) Fixed-length Array Declarations\fP are just like C array declarations:
  2030. X.DS L
  2031. X.ft CW
  2032.     fixed-array-declaration:
  2033.         type-ident variable-ident "[" value "]"
  2034. X.DE
  2035. Example:
  2036. X.DS L
  2037. X.ft CW
  2038.     colortype palette[8];    --> colortype palette[8];
  2039. X.DE
  2040. \fB3) Variable-Length Array Declarations\fP have no explicit syntax 
  2041. in C, so XDR invents its own using angle-brackets.
  2042. X.DS L
  2043. X.ft CW
  2044. variable-array-declaration:
  2045.     type-ident variable-ident "<" value ">"
  2046.     type-ident variable-ident "<" ">"
  2047. X.DE
  2048. The maximum size is specified between the angle brackets. The size may
  2049. be omitted, indicating that the array may be of any size.
  2050. X.DS L
  2051. X.ft CW
  2052.     int heights<12>;    /* \fIat most 12 items\fP */
  2053.     int widths<>;       /* \fIany number of items\fP */
  2054. X.DE
  2055. Since  variable-length  arrays have no  explicit  syntax in  C,  these
  2056. declarations are actually  compiled into "struct"s.  For example,  the
  2057. "heights" declaration gets compiled into the following struct:
  2058. X.DS L
  2059. X.ft CW
  2060.     struct {
  2061.         u_int heights_len;  /* \fI# of items in array\fP */
  2062.         int *heights_val;   /* \fIpointer to array\fP */
  2063.     } heights;
  2064. X.DE
  2065. Note  that the number  of items in  the array is stored in  the "_len"
  2066. component  and the  pointer  to   the array is  stored  in  the "_val"
  2067. component. The first part of each of these component's names is the
  2068. same as the name of the declared XDR variable.
  2069. X.LP
  2070. \fB4) Pointer Declarations\fP are made in 
  2071. XDR  exactly as they  are  in C.  You  can't
  2072. really send pointers over the network,  but  you  can use XDR pointers
  2073. for sending recursive data types such as lists and trees.  The type is
  2074. actually called "optional-data", not "pointer", in XDR language.
  2075. X.DS L
  2076. X.ft CW
  2077.     pointer-declaration:
  2078.         type-ident "*" variable-ident
  2079. X.DE
  2080. Example:
  2081. X.DS L
  2082. X.ft CW
  2083.     listitem *next;  -->  listitem *next;
  2084. X.DE
  2085. X.NH 2
  2086. \&Special Cases
  2087. X.IX rpcgen "special cases" \fIrpcgen\fP
  2088. X.LP
  2089. There are a few exceptions to the rules described above.
  2090. X.LP
  2091. X.B Booleans:
  2092. C has no built-in boolean type. However, the RPC library does  a
  2093. boolean type   called 
  2094. X.I bool_t 
  2095. that   is either  
  2096. X.I TRUE 
  2097. or  
  2098. X.I FALSE .
  2099. Things declared as  type 
  2100. X.I bool 
  2101. in  XDR language  are  compiled  into
  2102. X.I bool_t 
  2103. in the output header file.
  2104. X.LP
  2105. Example:
  2106. X.DS L
  2107. X.ft CW
  2108.     bool married;  -->  bool_t married;
  2109. X.DE
  2110. X.B Strings:
  2111. C has  no built-in string  type, but  instead uses the null-terminated
  2112. "char *" convention.  In XDR  language, strings are declared using the
  2113. "string" keyword,  and  compiled into "char  *"s in the  output header
  2114. file. The  maximum size contained  in the angle brackets specifies the
  2115. maximum number of characters allowed in the  strings (not counting the
  2116. X.I NULL 
  2117. character). The maximum size may be left off, indicating a string
  2118. of arbitrary length.
  2119. X.LP
  2120. Examples:
  2121. X.DS L
  2122. X.ft CW
  2123.     string name<32>;    -->  char *name;
  2124.     string longname<>;  -->  char *longname;
  2125. X.DE
  2126. X.B "Opaque  Data:"
  2127. Opaque data is used in RPC and XDR to describe untyped  data, that is,
  2128. just  sequences of arbitrary  bytes.  It may be  declared  either as a
  2129. fixed or variable length array.
  2130. X.DS L
  2131. Examples:
  2132. X.ft CW
  2133.     opaque diskblock[512];  -->  char diskblock[512];
  2134.  
  2135.     opaque filedata<1024>;  -->  struct {
  2136.                                     u_int filedata_len;
  2137.                                     char *filedata_val;
  2138.                                  } filedata;
  2139. X.DE
  2140. X.B Voids:
  2141. In a void declaration, the variable is  not named.  The declaration is
  2142. just "void" and nothing else.  Void declarations can only occur in two
  2143. places: union definitions and program definitions (as the  argument or
  2144. result of a remote procedure).
  2145. Funky_Stuff
  2146. cd ..
  2147. echo more files to follow
  2148. exit
  2149.